/*
 * Copyright (c) 2016-2018 Hunan CNBOT Co., Ltd. All Rights Reserved.
 * FileName: CnbotsPriorityExecutor.java
 * @author: Clintonfang
 * @date: 18-12-12 上午4:23
 * @version: 1.0
 */

package com.cnbot.toolkit.threadpool.priority;

import java.util.Comparator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 带优先级的线程池
 *
 * @author Clintonfang
 * @version 1.0
 * @date 2018-12-12 06:28:26
 * @since 1.0.7
 */
public class CnbotsPriorityExecutor extends ThreadPoolExecutor {
	/**
	 * 核心线程池大小
	 */
	private static final int CORE_POOL_SIZE = 4;
	/**
	 * 最大线程池队列大小
	 */
	private static final int MAXIMUM_POOL_SIZE = 256;
	/**
	 * 保持存活时间，当线程数大于CORE_POOL_SIZE 的空闲线程能保持的最大时间
	 */
	private static final int KEEP_ALIVE = 1;
	/**
	 * 主要获取添加任务
	 */
	private static final AtomicLong SEQ_SEED = new AtomicLong(0);

	/**
	 * 线程队列方式 先进先出
	 */
	private static final Comparator<Runnable> FIFO = new Comparator<Runnable>() {
		@Override
		public int compare(Runnable o1, Runnable o2) {
			if (o1 instanceof CnbotsPriorityRunnable && o2 instanceof CnbotsPriorityRunnable) {
				CnbotsPriorityRunnable lpr = ((CnbotsPriorityRunnable) o1);
				CnbotsPriorityRunnable rpr = ((CnbotsPriorityRunnable) o2);
				int result = lpr.priority.ordinal() - rpr.priority.ordinal();
				return result == 0 ? (int) (lpr.seq - rpr.seq) : result;
			} else {
				return 0;
			}
		}
	};

	/**
	 * 线程队列方式 后进先出
	 */
	private static final Comparator<Runnable> LIFO = new Comparator<Runnable>() {
		@Override
		public int compare(Runnable o1, Runnable o2) {
			if (o1 instanceof CnbotsPriorityRunnable && o2 instanceof CnbotsPriorityRunnable) {
				CnbotsPriorityRunnable lpr = ((CnbotsPriorityRunnable) o1);
				CnbotsPriorityRunnable rpr = ((CnbotsPriorityRunnable) o2);
				int result = lpr.priority.ordinal() - rpr.priority.ordinal();
				return result == 0 ? (int) (rpr.seq - lpr.seq) : result;
			} else {
				return 0;
			}
		}
	};

	/**
	 * CnbotsPriorityExecutor 构造函数，默认工作线程数5
	 *
	 * @param fifo          优先级相同时, 等待队列的是否优先执行先加入的任务.
	 * @param threadFactory ThreadFactory
	 */
	public CnbotsPriorityExecutor(boolean fifo, ThreadFactory threadFactory) {
		this(CORE_POOL_SIZE, fifo, threadFactory);
	}

	/**
	 * CnbotsPriorityExecutor 构造函数
	 *
	 * @param poolSize      工作线程数
	 * @param fifo          优先级相同时, 等待队列的是否优先执行先加入的任务.
	 * @param threadFactory ThreadFactory
	 */
	public CnbotsPriorityExecutor(int poolSize, boolean fifo, ThreadFactory threadFactory) {
		this(poolSize, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, new PriorityBlockingQueue<>(MAXIMUM_POOL_SIZE, fifo ? FIFO : LIFO),
				threadFactory);
	}

	/**
	 * CnbotsPriorityExecutor 构造函数
	 *
	 * @param corePoolSize    核心线程大小
	 * @param maximumPoolSize 最大线程大小
	 * @param keepAliveTime   非核心线程存活时间
	 * @param unit            时间单位
	 * @param workQueue       BlockingQueue
	 * @param threadFactory   ThreadFactory
	 * @author Clintonfang
	 * @date 2018-12-12 06:30:46
	 */
	public CnbotsPriorityExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
			ThreadFactory threadFactory) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
	}

	/**
	 * 判断当前线程池是否繁忙
	 *
	 * @return true：忙，false，不忙
	 */
	public boolean isBusy() {
		return getActiveCount() >= getCorePoolSize();
	}

	/**
	 * 提交任务
	 *
	 * @param runnable 具体执行的任务
	 */
	@Override
	public void execute(Runnable runnable) {
		if (runnable instanceof CnbotsPriorityRunnable) {
			((CnbotsPriorityRunnable) runnable).seq = SEQ_SEED.getAndIncrement();
		}
		super.execute(runnable);
	}
}
